import numpy as np
import pygame
import sys
import copy
import GameAI

"""
v_1.1 版本:

现有功能:
1. 游戏主页面
2. pvp 双人对弈
3. pve 人机对弈(功能偏弱)
4. 游戏结束结算界面

新增功能:
1. 游戏主页面
2. pve 人机对弈(功能偏弱)

"""


class CN_Chess_Game(object):
    """
    中国象棋游戏类
    """

    def __init__(self):
        """
        初始化函数
        """
        # Pygame 初始化
        pygame.init()

        # 设置窗口大小和标题
        WIDTH, HEIGHT = 450, 500  # 基于棋盘大小的窗口
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption('中国象棋')

        self.mode = "index"  # 可选值： "index"、"pvp"、"pve"、"settle"
        self._settlement_text = ""

        self.CN_chess_pieces_table = {
            -1: "帅", -2: "仕", -3: "相", -4: "马", -5: "车", -6: "炮", -7: "兵",
            1: "将", 2: "士", 3: "象", 4: "馬", 5: "車", 6: "砲", 7: "卒",
            0: None,
        }

        self.init_chess_position_table = {
            -1: [[9, 4]],
            -2: [[9, 3], [9, 5]],
            -3: [[9, 2], [9, 6]],
            -4: [[9, 1], [9, 7]],
            -5: [[9, 0], [9, 8]],
            -6: [[7, 1], [7, 7]],
            -7: [[6, 0], [6, 2], [6, 4], [6, 6], [6, 8]],
            1: [[0, 4]],
            2: [[0, 3], [0, 5]],
            3: [[0, 2], [0, 6]],
            4: [[0, 1], [0, 7]],
            5: [[0, 0], [0, 8]],
            6: [[2, 1], [2, 7]],
            7: [[3, 0], [3, 2], [3, 4], [3, 6], [3, 8]],
        }

        self.chess_position_table = copy.deepcopy(self.init_chess_position_table)

        self.CN_chess_board = np.zeros((10, 9), dtype=int)  # 10x9的棋盘，考虑了边界
        self.action_color = -1

        # 游戏状态控制
        self.game_over = False
        self.winner = 0  # -1 黑胜，1 红胜，0 进行中
        self.end_reason = ""  # 结束原因文本

        # 字体缓存
        self.font_large = pygame.font.Font("font/JyunsaiKaai-Bold.ttf", 48)
        self.font_medium = pygame.font.Font("font/JyunsaiKaai-Bold.ttf", 32)
        self.font_small = pygame.font.Font("font/JyunsaiKaai-Bold.ttf", 24)
        self.font_piece = pygame.font.Font("font/JyunsaiKaai-Bold.ttf", 22)  # 设定为可以输出中文的字体

        # 结算交互按钮的区域（会在结算画面中使用）
        self.btn_start_rect = None
        self.btn_quit_rect = None
        self.btn_quit_index_rect = None
        self.btn_pve_rect = None
        self.btn_pvp_rect = None

        self.chess_AI = GameAI.Chess_AI(self)

    # 控制台打印棋盘状态
    def print_piece_status(self):
        """
        打印棋子的状态信息
        :return:
        """
        print("当前局势:")
        for i in range(-7, -1 + 1):
            print(self.CN_chess_pieces_table[i] + ": ", end='')
            for j in self.chess_position_table[i]:
                print(j, end='')
                print(" ", end='')
            print('')

        for i in range(1, 7 + 1):
            print(self.CN_chess_pieces_table[i] + ": ", end='')
            for j in self.chess_position_table[i]:
                print(j, end='')
                print(" ", end='')
            print('')

    # 准备结算文本
    def _prepare_settlement_text(self, text):
        """
        准备结算文本，在结算画面中显示
        """
        self._settlement_text = text
        # 结算画面需要的按钮区域将在 draw 调用中绘制
        # 这里不额外做其它处理

    # 初始化对局状态
    def init_game(self):
        """
        初始化对局状态 用于新棋局的状态加载
        :return:
        """
        self.game_over = False
        self.action_color = -1
        self.winner = 0
        self._settlement_text = ""
        self.end_reason = ""  # 结束原因文本

    # 加载棋盘(后续可添加自定义棋局(残局))
    def init_chess_board(self):
        """
        初始化棋盘, 填充棋盘和初始化棋盘信息
        :return: None
        """
        self.CN_chess_board = np.zeros((10, 9), dtype=int)
        self.chess_position_table = copy.deepcopy(self.init_chess_position_table)

        for i in range(-7, 0):
            for j in self.init_chess_position_table[i]:
                self.CN_chess_board[j[0]][j[1]] = i

        for i in range(1, 8):
            for j in self.init_chess_position_table[i]:
                self.CN_chess_board[j[0]][j[1]] = i

        return self.CN_chess_board

    # 棋子移动API
    def move_chess_piece(self, origin_pos, aim_pos):
        """
        用于移动棋子
        :param origin_pos: 棋子的原坐标
        :param aim_pos: 棋子的目标坐标
        :return: 原坐标棋子的类别和目标坐标棋子类别
        """
        piece_1 = self.CN_chess_board[origin_pos[0]][origin_pos[1]]
        piece_2 = self.CN_chess_board[aim_pos[0]][aim_pos[1]]

        if piece_1 != 0:
            # 修改棋盘
            self.CN_chess_board[origin_pos[0]][origin_pos[1]] = 0
            self.CN_chess_board[aim_pos[0]][aim_pos[1]] = piece_1
            # 同步坐标表
            self.chess_position_table[piece_1].remove([origin_pos[0], origin_pos[1]])
            self.chess_position_table[piece_1].append([aim_pos[0], aim_pos[1]])
            if piece_2 != 0:
                self.chess_position_table[piece_2].remove([aim_pos[0], aim_pos[1]])

        return piece_1, piece_2

    # 回溯棋盘(悔棋)
    def reverse_chess_pieces(self, piece_1: int, piece_2: int, pos_1, pos_2):
        """
        动作回溯函数
        :param piece_1: 上一步操作的棋子
        :param piece_2: 上一步操作吃掉的棋子(可以为0)
        :param pos_1: 上一步操作前的棋子位置(原为piece_1 的位置)
        :param pos_2: 上一步操作后棋子的位置(原为piece_2 的位置)
        :return: None
        """
        self.CN_chess_board[pos_1[0]][pos_1[1]] = piece_1
        self.CN_chess_board[pos_2[0]][pos_2[1]] = piece_2
        if piece_1 != 0:
            self.chess_position_table[piece_1].remove([pos_2[0], pos_2[1]])
            self.chess_position_table[piece_1].append([pos_1[0], pos_1[1]])
        if piece_2 != 0:
            self.chess_position_table[piece_2].append([pos_2[0], pos_2[1]])

    # 生成基础行动点
    def create_move_point(self, chess_pie: int, position, out_list=False):
        """
        生成棋子的移动点
        :param chess_pie: 棋子
        :param position: 棋子的位置
        :param out_list 是否输出为列表的形式 默认输出为 nd.array 的形式
        :return: 棋子的移动点
        """
        if chess_pie == 0:
            return np.array([])

        valid_moves = []

        if chess_pie == 1 or chess_pie == -1:
            # 将帅的基本走法
            mt = np.array([[0, 1], [0, -1], [1, 0], [-1, 0]])
            for move in mt:
                new_pos = position + move
                if ((0 <= new_pos[0] <= 2 or 7 <= new_pos[0] <= 9) and 3 <= new_pos[1] <= 5) and \
                        (self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie <= 0):
                    valid_moves.append(new_pos)

                if move[0] != 0:
                    for step in range(1, 10):
                        new_pos = position + np.array([move[0] * step, move[1] * step])
                        if not (0 <= new_pos[0] < 10 and 0 <= new_pos[1] < 9):
                            break
                        if self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie == 0:
                            continue
                        if self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie == -1:
                            valid_moves.append(new_pos)
                            break
                        else:
                            break

        elif chess_pie == 2 or chess_pie == -2:
            # 仕士的基本走法
            mt = np.array([[1, 1], [-1, -1], [1, -1], [-1, 1]])
            for move in mt:
                new_pos = position + move
                if ((0 <= new_pos[0] <= 2 or 7 <= new_pos[0] <= 9) and 3 <= new_pos[1] <= 5) and \
                        (self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie <= 0):
                    valid_moves.append(new_pos)

        elif chess_pie == 3 or chess_pie == -3:
            # 象的基本走法
            mt = np.array([[2, 2], [-2, -2], [2, -2], [-2, 2]])
            for move in mt:
                new_pos = position + move
                if (0 <= new_pos[0] <= 4 if chess_pie == 3 else 5 <= new_pos[0] <= 9) and \
                        (0 <= new_pos[1] <= 8) and \
                        (self.CN_chess_board[position[0] + int(move[0] / 2)][position[1] + int(move[1] / 2)] == 0) and \
                        self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie <= 0:
                    valid_moves.append(new_pos)

        elif chess_pie == 4 or chess_pie == -4:
            # 马的基本走法
            mt = np.array([[1, 0], [-1, 0], [0, 1], [0, -1]])
            for move in mt:
                # 判断是否蹩马腿
                horse_leg = position + move
                if 9 >= horse_leg[0] >= 0 and 8 >= horse_leg[1] >= 0 == self.CN_chess_board[horse_leg[0], horse_leg[1]]:
                    # 如果不蹩马腿 则先生成最基础的落点
                    new_pos1 = horse_leg + move
                    new_pos2 = horse_leg + move
                    if move[0] != 0:
                        new_pos1[1] += 1
                        new_pos2[1] -= 1
                    else:
                        new_pos1[0] += 1
                        new_pos2[0] -= 1
                    # 最后再排除越界 己方棋子占格和双王见面的情况
                    if (0 <= new_pos1[0] <= 9 and 0 <= new_pos1[1] <= 8) and \
                            (self.CN_chess_board[new_pos1[0], new_pos1[1]] * chess_pie <= 0):
                        valid_moves.append(new_pos1)

                    if (0 <= new_pos2[0] <= 9 and 0 <= new_pos2[1] <= 8) and \
                            (self.CN_chess_board[new_pos2[0], new_pos2[1]] * chess_pie <= 0):
                        valid_moves.append(new_pos2)

        elif chess_pie == 5 or chess_pie == -5:
            # 车的基本走法
            directions = np.array([[1, 0], [-1, 0], [0, 1], [0, -1]])
            for direction in directions:
                for step in range(1, 10):  # 车可以走的最大步数
                    new_pos = position + np.array([direction[0] * step, direction[1] * step])
                    if not (0 <= new_pos[0] < 10 and 0 <= new_pos[1] < 9):
                        break
                    if self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie <= 0:
                        valid_moves.append(new_pos)
                        if self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie < 0:
                            break
                    else:
                        break

        elif chess_pie == 6 or chess_pie == -6:
            # 炮的基本走法
            directions = np.array([[1, 0], [-1, 0], [0, 1], [0, -1]])
            for direction in directions:
                # 是否遇到炮台
                is_fort_barbette = False
                for step in range(1, 10):
                    new_pos = position + np.array([direction[0] * step, direction[1] * step])
                    if not (0 <= new_pos[0] < 10 and 0 <= new_pos[1] < 9):
                        break
                    # 第一个遇到的子作为炮台
                    if not is_fort_barbette and self.CN_chess_board[new_pos[0], new_pos[1]] != 0:
                        is_fort_barbette = True
                        continue

                    # 分别处理是否有炮台的情况
                    # 无炮台的情况
                    if not is_fort_barbette:
                        valid_moves.append(new_pos)
                    # 有炮台的情况
                    else:
                        # 存在炮台时遇到的第一个对方棋子可以是炮的落点
                        if self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie < 0:
                            valid_moves.append(new_pos)
                            break
                        # 两个炮架无落点
                        elif self.CN_chess_board[new_pos[0], new_pos[1]] * chess_pie > 0:
                            break

        elif chess_pie == 7 or chess_pie == -7:
            # 兵卒的基本走法
            mt = np.array([[int(chess_pie / 7), 0], [0, 1], [0, -1]])
            for move in mt:
                new_pos = position + move
                if not (0 <= new_pos[0] < 10 and 0 <= new_pos[1] < 9):
                    continue

                if position[0] <= 4 if chess_pie == 7 else 5 <= position[0]:
                    if self.CN_chess_board[new_pos[0]][new_pos[1]] * chess_pie <= 0:
                        valid_moves.append(new_pos)
                    break

                elif self.CN_chess_board[new_pos[0]][new_pos[1]] * chess_pie <= 0:
                    valid_moves.append(new_pos)
        if out_list:
            return [x.tolist() if isinstance(x, np.ndarray) else x for x in valid_moves]
        return valid_moves

    # 获取合法移动点
    def get_legal_movement_points(self, origin_pos):
        """
        获取不会判负的合法走棋点
        :param origin_pos: 走棋点
        :return: 合法点数组
        """
        # 解析棋子类型
        piece = self.CN_chess_board[origin_pos[0]][origin_pos[1]]
        # 如果为空格 则返回空数组
        if piece == 0:
            return np.array([])
        # 解析出该棋子所有可用走法
        all_aim_pos = self.create_move_point(piece, origin_pos, out_list=True)
        all_legal_pos = self.create_move_point(piece, origin_pos, out_list=True)
        # 每一个走法都进行推演
        for aim_pos in all_aim_pos:
            pe_1, pe_2 = self.move_chess_piece(origin_pos, aim_pos)
            self_king_pos = self.chess_position_table[-1][0] if piece < 0 else self.chess_position_table[1][0]

            enemy_landing_points = []
            # 将敌方棋子的所有落点罗列
            for pie in range(
                    -7 if piece > 0 else 1,
                    0 if piece > 0 else 8
            ):
                for e_pos in self.chess_position_table[pie]:
                    for el_pos in self.create_move_point(pie, e_pos):
                        enemy_landing_points.append(el_pos)
            # 与我方将帅位置进行对照
            for enemy_landing_point in enemy_landing_points:
                if enemy_landing_point[0] == self_king_pos[0] and enemy_landing_point[1] == self_king_pos[1]:
                    try:
                        all_legal_pos.remove(aim_pos)
                    except Exception:
                        pass

            # 验证完成 回溯棋盘
            self.reverse_chess_pieces(pe_1, pe_2, origin_pos, aim_pos)
        # 筛选完成 返回合法移动点
        return np.array(all_legal_pos)

    # 切换行动方
    def change_action_color(self, ac=None):
        """
        用于改变行动方
        :param ac: -1 或 1 分别为红方和黑方
        :return: None
        """
        if ac is None:
            self.action_color = -self.action_color
        elif abs(ac) == 1:
            self.action_color = ac
        else:
            return

    # 胜负判定机
    def is_failed(self):
        """
        胜负判定节点函数
        :return: -1 黑胜 0 没有结果 1 红胜
        """
        available_action_count = 0
        # 黑方判负判定
        if self.action_color == 1:
            for i in range(1, 8):
                for pos in self.chess_position_table[i]:
                    available_action_count += self.get_legal_movement_points(pos).size
            if available_action_count == 0:
                print("红方胜")
                return 1
        else:
            for i in range(-7, 0):
                for pos in self.chess_position_table[i]:
                    available_action_count += self.get_legal_movement_points(pos).size
            if available_action_count == 0:
                print("黑方胜")
                return -1
        return 0

    # 获取当前局势双方可移动点的数量
    def get_all_legal_movement_points_count(self):
        """
        获取当前局势双方可移动点的数量
        :return:
        red_count: 红方当前所有棋子可移动的数量
        black_count: 黑方当前所有棋子可移动的数量
        """
        red_count = 0
        black_count = 0
        for i in range(1, 8):
            for pos in self.chess_position_table[i]:
                black_count += self.get_legal_movement_points(pos).size

        for i in range(-7, 0):
            for pos in self.chess_position_table[i]:
                red_count += self.get_legal_movement_points(pos).size

        return red_count, black_count

    # 绘制棋盘和棋子
    def draw_board(self, chess_board, selected_piece, valid_moves, show_settle=False, winner_text=""):
        """
        用于绘制棋盘
        :param chess_board: 绘制的棋盘对象 通常是 "self.CN_chess_board"
        :param selected_piece: 当前画面玩家选中的棋子(不为空时都会绘制可移动标注点)
        :param valid_moves: 选中棋子的可移动合法点列表
        :param show_settle: 是否为结算画面状态 如果为结算画面状态则绘制结算画面
        :param winner_text: 结算画面文本(红方胜, 黑方胜, 和棋等)
        :return:
        """
        # 一个单元格的长宽长度
        cell_length = 50
        # 棋子半径
        piece_rad = 20
        # 起始点
        board_origin_x = 25
        board_origin_y = 25
        # 线颜色
        line_color = (0, 0, 0)
        line_width = 3
        # 填充棋盘底色
        self.screen.fill((225, 198, 166))
        # 米字线坐标位置
        dash_line_pos = [
            (3, 0, 5, 2), (3, 7, 5, 9),
            (5, 0, 3, 2), (5, 7, 3, 9),
        ]
        # 十字标记位置
        loc_sign_pos = [
            (1, 2, 1, 1), (7, 2, 1, 1),
            (0, 3, 0, 1), (2, 3, 1, 1), (4, 3, 1, 1), (6, 3, 1, 1), (8, 3, 1, 0),
            (1, 7, 1, 1), (7, 7, 1, 1),
            (0, 6, 0, 1), (2, 6, 1, 1), (4, 6, 1, 1), (6, 6, 1, 1), (8, 6, 1, 0),
        ]

        # 绘制内外框
        # 内框
        board_rect_ins = pygame.Rect(board_origin_x, board_origin_y, cell_length * 8 + 1, cell_length * 9 + 1)
        # 外框
        board_rect_out = pygame.Rect(
            board_origin_x * 0.7, board_origin_y * 0.7,
            (cell_length * 8) + (board_origin_x * 0.65) + 1, (cell_length * 9) + (board_origin_y * 0.65) + 1)
        # 绘制
        pygame.draw.rect(self.screen, line_color, board_rect_ins, line_width)
        pygame.draw.rect(self.screen, line_color, board_rect_out, int(line_width * 1.5))

        # 绘制横向线
        for row in range(1, 9):
            pygame.draw.line(
                self.screen,
                line_color,
                (board_origin_x, board_origin_y + (cell_length * row)),
                (board_origin_x + cell_length * 8, board_origin_y + (cell_length * row)),
                width=line_width
            )
        # 绘制纵向线
        for col in range(1, 8):
            # 过河处不画横纵线
            pygame.draw.line(
                self.screen,
                line_color,
                (board_origin_x + (cell_length * col), board_origin_y),
                (board_origin_x + (cell_length * col), board_origin_y + cell_length * 4),
                width=line_width
            )

            pygame.draw.line(
                self.screen,
                line_color,
                (board_origin_x + (cell_length * col), board_origin_y + cell_length * 5),
                (board_origin_x + (cell_length * col), board_origin_y + cell_length * 9),
                width=line_width
            )

        # 绘制九宫格
        for pos in dash_line_pos:
            pygame.draw.line(
                self.screen,
                line_color,
                (board_origin_x + (cell_length * pos[0]), board_origin_y + (cell_length * pos[1])),
                (board_origin_x + (cell_length * pos[2]), board_origin_y + (cell_length * pos[3])),
                width=line_width + 1
            )

        # 绘制十字标记
        for pos in loc_sign_pos:
            if pos[2] == 1:
                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 0.8), (pos[1] * cell_length) + (board_origin_x * 0.8)),
                    ((pos[0] * cell_length) + (board_origin_x * 0.8) - (cell_length * 0.2),
                     (pos[1] * cell_length) + (board_origin_x * 0.8)),
                    width=line_width
                )
                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 0.8), (pos[1] * cell_length) + (board_origin_x * 0.8)),
                    ((pos[0] * cell_length) + (board_origin_x * 0.8),
                     (pos[1] * cell_length) + (board_origin_x * 0.8) - (cell_length * 0.2)),
                    width=line_width
                )

                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 0.8), (pos[1] * cell_length) + (board_origin_x * 1.2)),
                    ((pos[0] * cell_length) + (board_origin_x * 0.8) - (cell_length * 0.2),
                     (pos[1] * cell_length) + (board_origin_x * 1.2)),
                    width=line_width
                )
                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 0.8), (pos[1] * cell_length) + (board_origin_x * 1.2)),
                    ((pos[0] * cell_length) + (board_origin_x * 0.8),
                     (pos[1] * cell_length) + (board_origin_x * 1.2) + (cell_length * 0.2)),
                    width=line_width
                )

            if pos[3] == 1:
                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 1.2), (pos[1] * cell_length) + (board_origin_x * 1.2)),
                    ((pos[0] * cell_length) + (board_origin_x * 1.2) + (cell_length * 0.2),
                     (pos[1] * cell_length) + (board_origin_x * 1.2)),
                    width=line_width
                )
                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 1.2), (pos[1] * cell_length) + (board_origin_x * 1.2)),
                    ((pos[0] * cell_length) + (board_origin_x * 1.2),
                     (pos[1] * cell_length) + (board_origin_x * 1.2) + (cell_length * 0.2)),
                    width=line_width
                )

                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 1.2), (pos[1] * cell_length) + (board_origin_x * 0.8)),
                    ((pos[0] * cell_length) + (board_origin_x * 1.2) + (cell_length * 0.2),
                     (pos[1] * cell_length) + (board_origin_x * 0.8)),
                    width=line_width
                )
                pygame.draw.line(
                    self.screen,
                    line_color,
                    ((pos[0] * cell_length) + (board_origin_x * 1.2), (pos[1] * cell_length) + (board_origin_x * 0.8)),
                    ((pos[0] * cell_length) + (board_origin_x * 1.2),
                     (pos[1] * cell_length) + (board_origin_x * 0.8) - (cell_length * 0.2)),
                    width=line_width
                )

        # 楚河 汉界 字样
        center_y = board_origin_y + 4.5 * cell_length
        chuhan_text = self.font_medium.render("楚 河           汉 界", True, (0, 0, 0))
        ch_rect = chuhan_text.get_rect(center=(self.screen.get_width() // 2, center_y))
        self.screen.blit(chuhan_text, ch_rect)

        # 绘制棋子和提示符
        for row in range(10):
            for col in range(9):

                piece = chess_board[row][col]
                if piece != 0:
                    # 绘制棋子
                    color = (200, 0, 0) if piece < 0 else (0, 0, 0)  # 红色或黑色
                    pygame.draw.circle(
                        self.screen,
                        color,
                        (col * cell_length + board_origin_x, row * cell_length + board_origin_y),
                        piece_rad
                    )

                    # 在棋子上绘制编码
                    text = self.font_piece.render(self.CN_chess_pieces_table[piece], True, (255, 255, 255))
                    self.screen.blit(text, (col * 50 + 14, row * 50 + 11))

        # 标注可移动点
        if selected_piece is not None:
            for move in valid_moves:
                pygame.draw.circle(
                    self.screen,
                    (0, 205, 0),
                    (move[1] * cell_length + 25, move[0] * cell_length + 25),
                    int(piece_rad / 3)
                )

        # 如果在结算阶段，绘制结算信息
        if show_settle:
            self._draw_settlement_overlay(winner_text)

    # 主索引界面绘制
    def draw_index(self):
        """
        绘制主界面（索引/菜单）
        """
        self.screen.fill((240, 248, 255))  # 浅蓝白背景
        width, height = self.screen.get_size()

        # 标题
        title_surf = self.font_large.render("中国象棋", True, (30, 30, 60))
        title_rect = title_surf.get_rect(center=(width // 2, height // 5))
        self.screen.blit(title_surf, title_rect)

        # 按钮布局（响应式，适配窄屏）
        btn_w, btn_h = min(320, width - 40), 60
        gap = 20
        start_y = height // 3

        # 双人对弈按钮
        self.btn_pvp_rect = pygame.Rect((width - btn_w) // 2, start_y, btn_w, btn_h)
        pygame.draw.rect(self.screen, (70, 130, 180), self.btn_pvp_rect)
        text_pvp = self.font_medium.render("双人对弈", True, (255, 255, 255))
        t_pvp = text_pvp.get_rect(center=self.btn_pvp_rect.center)
        self.screen.blit(text_pvp, t_pvp)

        # 人机对弈按钮
        self.btn_pve_rect = pygame.Rect((width - btn_w) // 2, start_y + btn_h + gap, btn_w, btn_h)
        pygame.draw.rect(self.screen, (70, 130, 180), self.btn_pve_rect)
        text_pve = self.font_medium.render("人机对弈", True, (255, 255, 255))
        t_pve = text_pve.get_rect(center=self.btn_pve_rect.center)
        self.screen.blit(text_pve, t_pve)

        # 退出按钮
        self.btn_quit_index_rect = pygame.Rect((width - btn_w) // 2, start_y + 2 * (btn_h + gap), btn_w, btn_h)
        pygame.draw.rect(self.screen, (180, 0, 0), self.btn_quit_index_rect)
        text_quit = self.font_medium.render("退出", True, (255, 255, 255))
        t_quit = text_quit.get_rect(center=self.btn_quit_index_rect.center)
        self.screen.blit(text_quit, t_quit)

        # 简短提示
        tip = self.font_small.render("版本号: v1.1", True, (50, 50, 50))
        tip_rect = tip.get_rect(center=(width // 2, height - 40))
        self.screen.blit(tip, tip_rect)

    # 结算界面绘制
    def _draw_settlement_overlay(self, winner_text):
        """
        绘制一个半透明结算覆盖层，显示胜负信息与重新开始/退出按钮。
        """
        overlay = pygame.Surface(self.screen.get_size(), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 180))  # 半透明黑色背景
        self.screen.blit(overlay, (0, 0))

        # 结算标题
        title_surf = self.font_large.render("棋局结束", True, (255, 255, 255))
        title_rect = title_surf.get_rect(center=(self.screen.get_width() // 2, self.screen.get_height() // 3))
        self.screen.blit(title_surf, title_rect)

        # 胜负文本
        if winner_text:
            win_surf = self.font_medium.render(winner_text, True, (255, 255, 0))
            win_rect = win_surf.get_rect(center=(self.screen.get_width() // 2, self.screen.get_height() // 3 + 60))
            self.screen.blit(win_surf, win_rect)

        # 按钮配置（自适应简单布局）
        btn_w, btn_h = 180, 50
        gap = 20
        left = (self.screen.get_width() - btn_w) // 2
        top = self.screen.get_height() // 2

        # 重新开始按钮
        self.btn_start_rect = pygame.Rect(left, top, btn_w, btn_h)
        pygame.draw.rect(self.screen, (50, 205, 50), self.btn_start_rect)  # 绿色按钮
        start_text = self.font_medium.render("重新开始", True, (255, 255, 255))
        st_rect = start_text.get_rect(center=self.btn_start_rect.center)
        self.screen.blit(start_text, st_rect)

        # 退出按钮（现在改为返回主界面）
        self.btn_quit_rect = pygame.Rect(left, top + btn_h + gap, btn_w, btn_h)
        pygame.draw.rect(self.screen, (180, 0, 0), self.btn_quit_rect)  # 红色按钮
        quit_text = self.font_medium.render("返回主界面", True, (255, 255, 255))
        q_rect = quit_text.get_rect(center=self.btn_quit_rect.center)
        self.screen.blit(quit_text, q_rect)

    # 入口：进入主界面并保持在主界面，等待用户选择
    def index(self):
        """
        启动并保持在主界面，等待用户选择进入对局或退出
        """
        self.mode = "index"
        self.draw_index()
        pygame.display.flip()

        while self.mode == "index":
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit(0)

                elif event.type == pygame.MOUSEBUTTONDOWN:
                    x, y = event.pos
                    if self.btn_pvp_rect.collidepoint((x, y)):
                        # 进入双人对弈
                        self.mode = "pvp"
                        self.init_game()
                        self.init_chess_board()
                        self.main_pvp()
                        # 回到主界面
                        self.mode = "index"
                        self.draw_index()
                        pygame.display.flip()
                    elif self.btn_pve_rect.collidepoint((x, y)):
                        # 进入人机对弈（功能较弱）
                        self.mode = "pve"
                        self.init_game()
                        self.init_chess_board()
                        self.main_pve()
                        # 回到主界面
                        self.mode = "index"
                        self.draw_index()
                        pygame.display.flip()
                    elif self.btn_quit_index_rect.collidepoint((x, y)):
                        pygame.quit()
                        sys.exit(0)
            # 简单动画刷新
            pygame.display.flip()
        # 退出清理
        pygame.quit()

    # 启动PvP对弈
    def main_pvp(self):
        """
        pvp 对弈
        :return: None
        """
        selected_piece = None
        valid_moves = []

        running = True

        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

                elif event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_x, mouse_y = event.pos
                    col = mouse_x // 50
                    row = mouse_y // 50

                    if self.game_over:
                        # 处理结算画面的按钮点击
                        if self.btn_start_rect and self.btn_start_rect.collidepoint((mouse_x, mouse_y)):
                            # 重新开始
                            self.init_game()  # 重新初始化
                            self.init_chess_board()
                            selected_piece = None
                            valid_moves = []
                            continue
                        if self.btn_quit_rect and self.btn_quit_rect.collidepoint((mouse_x, mouse_y)):
                            running = False
                            continue
                        # 其他区域点按忽略
                        continue
                    # 只有行动方可执棋
                    if selected_piece is None and self.CN_chess_board[row][col] * self.action_color > 0:
                        selected_piece = (row, col)
                        valid_moves = self.get_legal_movement_points(np.array([row, col]))

                    elif selected_piece is not None:
                        # 检查是否点击了有效移动点
                        if any((move[0] == row and move[1] == col) for move in valid_moves):
                            # 如果是合法移动，则移动棋子
                            self.move_chess_piece(
                                [selected_piece[0], selected_piece[1]],
                                [row, col]
                            )
                            selected_piece = None
                            valid_moves = []
                            # 切换行动方
                            self.change_action_color()
                            # 判断胜负
                            res = self.is_failed()
                            if res != 0:
                                # 进入结算画面
                                self.game_over = True
                                self.winner = res
                                self.end_reason = "因无可行动棋子，局面结束"  # 可按实际情况扩展
                                if res == 1:
                                    self.end_reason = "红方胜利"
                                elif res == -1:
                                    self.end_reason = "黑方胜利"
                                settlement_text = f"{self.end_reason}"
                                # 在结算画面中显示文本
                                self._prepare_settlement_text(settlement_text)
                            else:
                                pass
                        else:
                            # 如果点击了无效点，重置状态
                            selected_piece = None
                            valid_moves = []

            # 绘制
            show_settle = self.game_over
            settle_text = getattr(self, "_settlement_text", "")

            self.draw_board(self.CN_chess_board, selected_piece, valid_moves, show_settle=show_settle,
                            winner_text=settle_text)

            # 简单动画刷新
            pygame.display.flip()

    # 启动PVE对弈
    def main_pve(self):
        """
        人机对弈
        :return:
        """
        selected_piece = None
        valid_moves = []

        running = True

        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

                # 电脑执棋
                elif self.action_color > 0 and not self.game_over:
                    all_pos = self.chess_AI.calculate_res(self.action_color)
                    if all_pos is not None:
                        self.move_chess_piece(all_pos[0], all_pos[1])
                        self.change_action_color()

                # elif self.action_color < 0 and not self.game_over:
                #     all_pos = self.chess_AI.calculate_res(self.action_color)
                #     if all_pos is not None:
                #         self.move_chess_piece(all_pos[0], all_pos[1])
                #         self.change_action_color()

                elif event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_x, mouse_y = event.pos
                    col = mouse_x // 50
                    row = mouse_y // 50

                    if self.game_over:
                        # 处理结算画面的按钮点击
                        if self.btn_start_rect and self.btn_start_rect.collidepoint((mouse_x, mouse_y)):
                            # 重新开始
                            self.init_game()  # 重新初始化
                            self.init_chess_board()
                            selected_piece = None
                            valid_moves = []
                            continue
                        if self.btn_quit_rect and self.btn_quit_rect.collidepoint((mouse_x, mouse_y)):
                            running = False
                            continue
                        # 其他区域点按忽略
                        continue
                    # 玩家执棋
                    if selected_piece is None and self.CN_chess_board[row][col] * self.action_color > 0:
                        selected_piece = (row, col)
                        valid_moves = self.get_legal_movement_points(np.array([row, col]))
                        continue

                    elif selected_piece is not None:
                        # 检查是否点击了有效移动点
                        if any((move[0] == row and move[1] == col) for move in valid_moves):
                            # 如果是合法移动，则移动棋子
                            self.move_chess_piece(
                                [selected_piece[0], selected_piece[1]],
                                [row, col]
                            )
                            selected_piece = None
                            valid_moves = []
                            # 切换行动方
                            self.change_action_color()
                        else:
                            # 如果点击了无效点，重置状态
                            selected_piece = None
                            valid_moves = []

                    # 判断胜负
                    res = self.is_failed()
                    if res != 0:
                        # 进入结算画面
                        self.game_over = True
                        self.winner = res
                        self.end_reason = "因无可行动棋子，局面结束"  # 可按实际情况扩展
                        if res == 1:
                            self.end_reason = "红方胜利"
                        elif res == -1:
                            self.end_reason = "黑方胜利"
                        settlement_text = f"{self.end_reason}"
                        # 在结算画面中显示文本
                        self._prepare_settlement_text(settlement_text)

            # 绘制结束文本
            show_settle = self.game_over
            settle_text = getattr(self, "_settlement_text", "")

            self.draw_board(self.CN_chess_board, selected_piece, valid_moves, show_settle=show_settle,
                            winner_text=settle_text)
            # self.print_piece_status()
            # 简单动画刷新
            pygame.display.flip()


# 如果直接运行脚本，执行游戏
if __name__ == '__main__':
    cn_chess_game = CN_Chess_Game()
    cn_chess_game.index()
